<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      function Father(username) {
        this.username = username
      }

      Father.prototype.sayHi = function () {
        console.log('hi')
      }

      //   1. 原型链继承
      //   原型链继承是通过将子类的原型指向父类的实例来实现继承。这种方式简单易懂，但是会存在引用类型共享和无法向父类传递参数等缺点。
      //   2. 构造函数继承
      //   构造函数继承是通过在子类的构造函数中通过call借调父类的构造函数来实现继承。这种方式可以避免引用类型共享的问题，但是无法继承父类的原型上的属性和方法。
      //   3. 组合继承
      //   组合继承是将原型链继承和构造函数继承组合使用，既能继承父类原型上的属性和方法，又能避免引用类型共享的问题，但是会存在重复调用父类构造函数的问题。
      //   4. 原型式继承
      //   原型式继承是通过复制一个对象来实现继承，这种方式可以实现类似于对象的克隆，但是会存在引用类型共享的问题。
      //   5. 寄生式继承
      //   寄生式继承是在原型式继承的基础上添加一些扩展方法来实现继承，但是同样会存在引用类型共享的问题。
      //   6. 寄生组合式继承
      //   寄生组合式继承是在组合继承的基础上进行优化，避免重复调用父类构造函数，可以实现继承父类原型上的属性和方法，并避免引用类型共享的问题。
    </script>
  </body>
</html>
